<script setup lang="ts">
import { ref, computed, onMounted, watch } from 'vue'
import { useDraggable, useScroll } from '@vueuse/core'
import { useGanttStore } from '../stores/ganttStore'
import type { Flight } from '../types/flight'
import {
  getThreeDaysRange,
  timeToPixels,
  generateTimeMarks,
  formatTime,
  formatDateTime,
  getDurationMinutes,
  PIXELS_PER_HOUR
} from '../utils/timeUtils'
import { ElDatePicker, ElButton, ElCheckboxGroup, ElCheckbox, ElPopover, ElMessage } from 'element-plus'

const ganttStore = useGanttStore()

// 响应式变量
const scrollContainer = ref<HTMLElement | null>(null)
const ganttContent = ref<HTMLElement | null>(null)
const selectedDate = ref(new Date())
const draggingFlight = ref<Flight | null>(null)
const dragPreview = ref<HTMLElement | null>(null)
const dragOffset = ref({ x: 0, y: 0 }) // 鼠标相对于航班起始位置的偏移
const dragStartPos = ref({ x: 0, y: 0 }) // 拖拽开始时的鼠标位置
const isDragging = ref(false) // 是否真正开始拖拽（移动超过阈值）
const DRAG_THRESHOLD = 5 // 拖拽阈值（像素）
const timeIndicator = ref<{ show: boolean; time: string; x: number }>({
  show: false,
  time: '',
  x: 0
})

// 机位选择器
const gateSelectVisible = ref(false)
const selectedGates = ref<string[]>([])

// 时间轴滚动
const { x: scrollX, arrivedState } = useScroll(scrollContainer, {
  behavior: 'smooth'
})

// 时间轴拖拽
const timeAxisDragging = ref(false)
const timeAxisDragStart = ref({ x: 0, scrollX: 0 })

// 计算属性
const timeRange = computed(() => getThreeDaysRange(ganttStore.currentDate))
const timeMarks = computed(() => generateTimeMarks(timeRange.value.start, timeRange.value.end))

// 总宽度计算（3天 = 72小时）
const totalWidth = computed(() => 72 * PIXELS_PER_HOUR)

// 行高
const rowHeight = 50

// 获取航班的样式
const getFlightStyle = (flight: Flight) => {
  const left = timeToPixels(flight.startTime, timeRange.value.start)
  const width = timeToPixels(flight.endTime, timeRange.value.start) - left

  // 根据状态设置背景色和透明度
  let backgroundColor = '#3b82f6' // 默认蓝色
  let opacity = '1'

  if (flight.status === 'warning') {
    // 冲突状态：半透明红色，可以看到下层航班
    backgroundColor = '#ef4444'
    opacity = '0.7'
  } else if (flight.status === 'conflict') {
    backgroundColor = '#10b981'
  }

  return {
    left: `${left}px`,
    width: `${width}px`,
    backgroundColor,
    opacity,
    zIndex: flight.zIndex || 0
  }
}

// 获取机位行的样式
const getGateRowStyle = (index: number) => {
  return {
    height: `${rowHeight}px`,
    top: `${index * rowHeight}px`
  }
}

// 日期改变
const onDateChange = (date: Date) => {
  ganttStore.setCurrentDate(date)
  // 滚动到中间位置
  scrollToCenter()
}

// 滚动到中间位置（当前时间）
const scrollToCenter = () => {
  if (!scrollContainer.value) return

  const now = new Date()
  const centerTime = new Date(ganttStore.currentDate)
  centerTime.setHours(now.getHours(), now.getMinutes(), 0, 0)

  const centerX = timeToPixels(centerTime, timeRange.value.start)
  const containerWidth = scrollContainer.value.clientWidth

  scrollX.value = centerX - containerWidth / 2
}

// 时间轴拖拽开始
const onTimeAxisMouseDown = (e: MouseEvent) => {
  if (!scrollContainer.value) return

  // 只在时间轴和网格区域触发拖拽，排除航班条
  const target = e.target as HTMLElement
  if (target.closest('.flight-bar')) return
  if (!target.closest('.time-axis') && !target.closest('.gantt-grid')) return

  timeAxisDragging.value = true
  timeAxisDragStart.value = {
    x: e.clientX,
    scrollX: scrollX.value
  }

  document.addEventListener('mousemove', onTimeAxisMouseMove)
  document.addEventListener('mouseup', onTimeAxisMouseUp)

  e.preventDefault()
}

// 时间轴拖拽移动
const onTimeAxisMouseMove = (e: MouseEvent) => {
  if (!timeAxisDragging.value) return

  const deltaX = timeAxisDragStart.value.x - e.clientX
  scrollX.value = timeAxisDragStart.value.scrollX + deltaX
}

// 时间轴拖拽结束
const onTimeAxisMouseUp = () => {
  timeAxisDragging.value = false
  document.removeEventListener('mousemove', onTimeAxisMouseMove)
  document.removeEventListener('mouseup', onTimeAxisMouseUp)
}

// 航班拖拽开始
const onFlightDragStart = (flight: Flight, e: MouseEvent) => {
  if (!ganttContent.value || !scrollContainer.value) return

  draggingFlight.value = flight
  isDragging.value = false // 初始状态不是拖拽，需要移动超过阈值

  // 记录拖拽开始位置
  dragStartPos.value = {
    x: e.clientX,
    y: e.clientY
  }

  // 记录点击位置相对于航班条左上角的偏移（用于拖拽预览显示）
  const target = e.currentTarget as HTMLElement
  const targetRect = target.getBoundingClientRect()

  dragOffset.value = {
    x: e.clientX - targetRect.left,
    y: e.clientY - targetRect.top
  }

  document.addEventListener('mousemove', onFlightDragMove)
  document.addEventListener('mouseup', onFlightDragEnd)

  e.stopPropagation() // 阻止事件冒泡，避免触发时间轴拖拽
  e.preventDefault()
}

// 统一的位置计算函数：从鼠标位置计算航班应该放置的机位（时间保持不变）
const calculateFlightPosition = (_mouseX: number, mouseY: number) => {
  if (!ganttContent.value || !scrollContainer.value || !draggingFlight.value) return null

  // 使用 scrollContainer 的边界
  const scrollRect = scrollContainer.value.getBoundingClientRect()

  // 计算航班左上角的位置（屏幕坐标）
  const flightScreenY = mouseY - dragOffset.value.y

  // 时间保持不变，使用航班的原始起始时间
  const time = draggingFlight.value.startTime

  // 计算航班在屏幕上的 X 位置（基于原始时间）
  const flightContentX = timeToPixels(time, timeRange.value.start)
  const flightScreenX = scrollRect.left + flightContentX - scrollContainer.value.scrollLeft

  // 时间轴在 scrollContainer 上方，所以 Y 坐标需要减去时间轴的高度（48px）
  const timeAxisHeight = 48
  const flightContentY = (flightScreenY - scrollRect.top) - timeAxisHeight

  // 计算机位（使用航班中心位置判断）
  const gateIndex = Math.floor((flightContentY + rowHeight / 2) / rowHeight)

  return {
    time, // 时间不变
    gateIndex,
    screenX: flightScreenX, // X 位置锁定在原始时间
    screenY: flightScreenY  // Y 位置跟随鼠标
  }
}

// 航班拖拽移动
const onFlightDragMove = (e: MouseEvent) => {
  if (!draggingFlight.value || !scrollContainer.value || !ganttContent.value) return

  // 检查是否超过拖拽阈值
  const deltaX = Math.abs(e.clientX - dragStartPos.value.x)
  const deltaY = Math.abs(e.clientY - dragStartPos.value.y)
  const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY)

  // 如果还没有真正开始拖拽，检查是否超过阈值
  if (!isDragging.value) {
    if (distance < DRAG_THRESHOLD) {
      return // 还没超过阈值，不做任何处理
    }
    // 超过阈值，开始真正的拖拽
    isDragging.value = true
  }

  // 创建拖拽预览（如果还没创建）
  if (!dragPreview.value) {
    const flightEl = document.querySelector(`[data-flight-id="${draggingFlight.value.id}"]`) as HTMLElement
    if (flightEl) {
      const clone = flightEl.cloneNode(true) as HTMLElement
      clone.style.opacity = '0.8'
      clone.style.position = 'fixed'
      clone.style.pointerEvents = 'none'
      clone.style.zIndex = '9999'
      clone.style.width = flightEl.offsetWidth + 'px'
      clone.style.height = flightEl.offsetHeight + 'px'
      clone.style.display = 'none' // 初始隐藏

      // 设置初始位置为航班的原始位置
      const flightRect = flightEl.getBoundingClientRect()
      clone.style.left = `${flightRect.left}px`
      clone.style.top = `${flightRect.top}px`

      dragPreview.value = clone
      document.body.appendChild(clone)
    }
  }

  // 计算位置
  const position = calculateFlightPosition(e.clientX, e.clientY)
  if (!position) return

  // 更新拖拽预览位置和显示状态
  if (dragPreview.value) {
    dragPreview.value.style.left = `${position.screenX}px`
    dragPreview.value.style.top = `${position.screenY}px`
    // 只有真正开始拖拽时才显示预览
    if (isDragging.value) {
      dragPreview.value.style.display = 'block'
    }
  }

  // 只有真正开始拖拽时才显示时间指示器和高亮
  if (isDragging.value) {
    // 显示时间指示器
    timeIndicator.value = {
      show: true,
      time: formatDateTime(position.time),
      x: position.screenX
    }

    // 高亮目标机位
    if (position.gateIndex >= 0 && position.gateIndex < ganttStore.visibleGates.length) {
      highlightTargetGate(position.gateIndex)
    }
  }
}

// 航班拖拽结束
const onFlightDragEnd = (e: MouseEvent) => {
  if (!draggingFlight.value) {
    cleanup()
    return
  }

  // 如果真正进行了拖拽（移动超过阈值），才更新位置
  if (isDragging.value) {
    // 使用统一的位置计算函数
    const position = calculateFlightPosition(e.clientX, e.clientY)

    if (position && position.gateIndex >= 0 && position.gateIndex < ganttStore.visibleGates.length) {
      const gate = ganttStore.visibleGates[position.gateIndex]

      if (gate) {
        // 检查冲突
        const duration = getDurationMinutes(draggingFlight.value.startTime, draggingFlight.value.endTime)
        const endTime = new Date(position.time.getTime() + duration * 60 * 1000)

        const hasConflict = ganttStore.checkFlightConflict(
          draggingFlight.value.id,
          gate.id,
          position.time,
          endTime
        )

        if (hasConflict) {
          // 显示警告但允许拖拽
          ElMessage.warning('航班时间与现有航班冲突，请注意!')
        }

        // 更新航班位置
        ganttStore.updateFlightPosition(draggingFlight.value.id, gate.id, position.time)
      }
    }
  } else {
    // 这是一个点击事件，不是拖拽
    // TODO: 在这里处理点击事件，例如显示航班详情
    console.log('航班被点击:', draggingFlight.value)
  }

  cleanup()
}

// 清理拖拽状态
const cleanup = () => {
  if (dragPreview.value) {
    document.body.removeChild(dragPreview.value)
    dragPreview.value = null
  }

  draggingFlight.value = null
  timeIndicator.value.show = false

  document.removeEventListener('mousemove', onFlightDragMove)
  document.removeEventListener('mouseup', onFlightDragEnd)

  // 清除高亮
  clearHighlight()
}

// 高亮目标机位
const highlightTargetGate = (gateIndex: number) => {
  clearHighlight()

  const gateRow = document.querySelector(`[data-gate-index="${gateIndex}"]`)
  if (gateRow) {
    gateRow.classList.add('highlight')
  }
}

// 清除高亮
const clearHighlight = () => {
  document.querySelectorAll('.highlight').forEach(el => {
    el.classList.remove('highlight')
  })
}

// 隐藏选中的机位
const hideSelectedGates = () => {
  if (selectedGates.value.length > 0) {
    ganttStore.hideGates(selectedGates.value)
    selectedGates.value = []
    gateSelectVisible.value = false
  }
}

// 显示所有机位
const showAllGates = () => {
  ganttStore.showAllGates()
  selectedGates.value = []
}

// 回到今天（当前日期和时间）
const scrollToToday = () => {
  const today = new Date()
  // 更新日期选择器和 store 中的日期
  selectedDate.value = today
  ganttStore.setCurrentDate(today)
  // 滚动到当前时间位置
  scrollToCenter()
}

// 组件挂载
onMounted(() => {
  ganttStore.initMockData()
  scrollToCenter()
})
</script>

<template>
  <div class="gantt-container">
    <!-- 顶部工具栏 -->
    <div class="toolbar">
      <div class="flex items-center gap-4">
        <ElDatePicker v-model="selectedDate" type="date" placeholder="选择日期" @change="onDateChange" />

        <ElPopover v-model:visible="gateSelectVisible" placement="bottom" :width="300" trigger="click">
          <template #reference>
            <ElButton>隐藏机位</ElButton>
          </template>

          <div class="gate-selector">
            <div class="mb-2 text-sm font-medium">选择要隐藏的机位:</div>
            <ElCheckboxGroup v-model="selectedGates" class="flex flex-col gap-2">
              <ElCheckbox v-for="gate in ganttStore.gates" :key="gate.id" :label="gate.id" :disabled="!gate.visible">
                {{ gate.name }}
              </ElCheckbox>
            </ElCheckboxGroup>

            <div class="mt-4 flex gap-2">
              <ElButton size="small" @click="hideSelectedGates">确定隐藏</ElButton>
              <ElButton size="small" @click="showAllGates">显示全部</ElButton>
            </div>
          </div>
        </ElPopover>

        <ElButton text @click="scrollToToday" title="回到今天" class="!ml-0">
          <el-icon :size="20">
            <Aim />
          </el-icon>
        </ElButton>
      </div>
    </div>

    <!-- 甘特图主体 -->
    <div class="gantt-wrapper">
      <!-- 左侧机位列 -->
      <div class="gates-column">
        <div class="gates-header">机位</div>
        <div class="gates-body">
          <div v-for="(gate, index) in ganttStore.visibleGates" :key="gate.id" class="gate-row"
            :style="{ height: `${rowHeight}px` }">
            {{ gate.name }}
          </div>
        </div>
      </div>

      <!-- 中间滚动区域 -->
      <div ref="scrollContainer" class="gantt-scroll" @mousedown="onTimeAxisMouseDown">
        <!-- 时间轴 -->
        <div class="time-axis" :style="{ width: `${totalWidth}px` }">
          <div v-for="mark in timeMarks" :key="mark.time.getTime()" class="time-mark"
            :class="mark.type === 'major' ? 'time-mark-major' : 'time-mark-minor'"
            :style="{ left: `${mark.position}px` }">
            <div v-if="mark.label" class="time-label">{{ mark.label }}</div>
            <div class="time-line"></div>
          </div>
        </div>

        <!-- 甘特图内容 -->
        <div ref="ganttContent" class="gantt-content"
          :style="{ width: `${totalWidth}px`, height: `${ganttStore.visibleGates.length * rowHeight}px` }">
          <!-- 网格背景 -->
          <div class="gantt-grid">
            <div v-for="(gate, index) in ganttStore.visibleGates" :key="gate.id" class="grid-row"
              :data-gate-index="index" :style="getGateRowStyle(index)">
              <div v-for="mark in timeMarks" :key="mark.time.getTime()" class="grid-cell"
                :class="mark.type === 'major' ? 'grid-cell-major' : 'grid-cell-minor'"
                :style="{ left: `${mark.position}px` }"></div>
            </div>
          </div>

          <!-- 航班条 -->
          <template v-for="flight in ganttStore.flights" :key="flight.id">
            <div v-if="ganttStore.visibleGates.findIndex(g => g.id === flight.gateId) >= 0" class="flight-bar"
              :data-flight-id="flight.id"
              :style="{
                ...getFlightStyle(flight),
                top: `${ganttStore.visibleGates.findIndex(g => g.id === flight.gateId) * rowHeight + 5}px`
              }" @mousedown="onFlightDragStart(flight, $event)">
              <div class="flight-content">
                <span class="flight-number">{{ flight.flightNumber }}</span>
                <span class="flight-time">{{ formatTime(flight.startTime) }} - {{ formatTime(flight.endTime) }}</span>
              </div>
            </div>
          </template>
        </div>
      </div>

      <!-- 右侧机位列 -->
      <div class="gates-column">
        <div class="gates-header">机位</div>
        <div class="gates-body">
          <div v-for="(gate, index) in ganttStore.visibleGates" :key="gate.id" class="gate-row"
            :style="{ height: `${rowHeight}px` }">
            {{ gate.name }}
          </div>
        </div>
      </div>
    </div>

    <!-- 时间指示器 -->
    <div v-if="timeIndicator.show" class="time-indicator" :style="{ left: `${timeIndicator.x}px` }">
      {{ timeIndicator.time }}
    </div>
  </div>
</template>

<style scoped>
@reference '../style.css'

.gantt-container {
  @apply w-full h-screen flex flex-col bg-gray-50;
}

.toolbar {
  @apply px-4 py-3 bg-white border-b border-gray-200 flex items-center justify-between;
}

.gantt-wrapper {
  @apply flex-1 flex overflow-hidden;
}

.gates-column {
  @apply w-24 bg-white border-r border-gray-200 flex flex-col shrink-0;
}

.gates-header {
  @apply h-12 flex items-center justify-center font-semibold border-b border-gray-200 bg-gray-100;
}

.gates-body {
  @apply flex-1 overflow-hidden;
}

.gate-row {
  @apply flex items-center justify-center border-b border-gray-200 text-sm font-medium;
}

.gantt-scroll {
  @apply flex-1 overflow-x-auto overflow-y-hidden relative;
  cursor: grab;
}

.gantt-scroll:active {
  cursor: grabbing;
}

.time-axis {
  @apply h-12 relative bg-gray-100 border-b border-gray-300;
}

.time-mark {
  @apply absolute top-0 h-full;
}

.time-mark-major .time-label {
  @apply text-xs text-center mt-1 font-medium text-gray-700;
}

.time-mark-major .time-line {
  @apply absolute top-6 left-0 w-px h-6 bg-gray-400;
}

.time-mark-minor .time-line {
  @apply absolute top-8 left-0 w-px h-4 bg-gray-300;
}

.gantt-content {
  @apply relative;
}

.gantt-grid {
  @apply absolute inset-0;
}

.grid-row {
  @apply absolute left-0 right-0 border-b border-gray-200;
}

.grid-row.highlight {
  @apply bg-blue-50;
}

.grid-cell {
  @apply absolute top-0 bottom-0;
}

.grid-cell-major {
  @apply border-r border-gray-300;
}

.grid-cell-minor {
  @apply border-r border-gray-100;
}

.flight-bar {
  @apply absolute h-10 rounded px-2 py-1 cursor-move shadow-sm hover:shadow-md transition-all;
  @apply text-white text-xs;
  /* 背景色、透明度和 z-index 通过内联样式控制 */
}

.flight-content {
  @apply flex flex-col justify-center h-full overflow-hidden;
}

.flight-number {
  @apply font-bold truncate;
}

.flight-time {
  @apply text-xs opacity-90 truncate;
}

.time-indicator {
  @apply fixed top-16 px-2 py-1 bg-blue-600 text-white text-xs rounded shadow-lg pointer-events-none z-50;
  transform: translateX(-50%);
}

.gate-selector {
  @apply max-h-96 overflow-y-auto;
}
</style>
